/**
 * 
 */
package jmath.io;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.LogAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import cern.colt.matrix.DoubleMatrix1D;
import jmath.io.data.*;

/**
 * @author timon
 * 
 */
public class JMathGraphPloter {
	private JFreeChart chart;

	private JMathXYDataset dataSet;

	private boolean rangeAxisIsLog = false;

	public boolean isRangeAxisIsLog() {
		return rangeAxisIsLog;
	}

	private JMathConsole jMathConsole;

	// //////////////////////////////////////////

	public JFreeChart createChart() {
		dataSet = new JMathXYDataset();
		chart = ChartFactory.createXYLineChart("", "X", "Y", dataSet,
				PlotOrientation.VERTICAL, true, true, false);

		XYPlot xyplot = (XYPlot) chart.getPlot();
		xyplot.getDomainAxis().setLowerMargin(0.0D);
		xyplot.getDomainAxis().setUpperMargin(0.0D);
		XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyplot
				.getRenderer();
		xylineandshaperenderer
				.setLegendLine(new java.awt.geom.Rectangle2D.Double(-4D, -3D,
						8D, 6D));
		return chart;
	}

	public void setTitle(String text) {
		chart.setTitle(text);
	}

	public void setLabels(String xLabel, String yLabel) {
		chart.getXYPlot().getDomainAxis().setLabel(xLabel);
		chart.getXYPlot().getRangeAxis().setLabel(yLabel);
	}

	private void newPlot(String name) {
		dataSet.createNewSeria(name);
	}

	public void clear() {
		dataSet.clearData();
		dataSet.viewData();
	}

	public void clear(String name) {
		dataSet.clearData(name);
		dataSet.viewData();
	}

	// //////////////////////////////////////

	public void plot(double[] x, double[] y) {
		plot(x, y, "");
	}

	public void plot(DoubleMatrix1D x, DoubleMatrix1D y) {
		plot(x, y, "");
	}

	public void semilogy(double[] x, double[] y) {
		semilogy(x, y, "");
	}

	public void semilogy(DoubleMatrix1D x, DoubleMatrix1D y) {
		semilogy(x, y, "");
	}

	// --------------------------------------

	public void plot(double[] x, double[] y, String name) {
		newPlot(name);
		if (x.length != y.length) {
			jMathConsole
					.warn("plot(double[] x,double[] y)-- x and y must be of same length");
			return;
		}
		//if (rangeAxisIsLog) {
			String label = chart.getXYPlot().getRangeAxis().getLabel();
			chart.getXYPlot().setRangeAxis(new NumberAxis(label));
			rangeAxisIsLog = false;
		//}
		for (int i = 0; i < x.length; i++) {
			dataSet.addNewDot(x[i], y[i]);
		}
		dataSet.viewData();
	}

	public void plot(DoubleMatrix1D x, DoubleMatrix1D y, String name) {
		newPlot(name);
		if (x == null || y == null || x.size() != x.size()) {
			jMathConsole
					.warn("plot(DoubleMatrix1D x,DoubleMatrix1D y)-- x and y must be of same size");
			return;
		}
		//if (rangeAxisIsLog) {
			String label = chart.getXYPlot().getRangeAxis().getLabel();
			chart.getXYPlot().setRangeAxis(new NumberAxis(label));
			rangeAxisIsLog = false;
		//}
		double maxY = 0;
		for (int i = 0; i < x.size(); i++) {
			if (maxY < y.get(i)) {
				maxY = y.get(i);
			}
		}
		for (int i = 0; i < x.size(); i++) {
			if ((maxY / y.get(i)) < 10000) {
				dataSet.addNewDot(x.get(i), y.get(i));
			}
		}
		dataSet.viewData();
	}

	public void semilogy(double[] x, double[] y, String name) {
		newPlot(name);
		if (x.length != y.length) {
			jMathConsole
					.warn("plot(double[] x,double[] y)-- x and y must be of same length");
			return;
		}
		//if (!rangeAxisIsLog) {
			String label = chart.getXYPlot().getRangeAxis().getLabel();
			chart.getXYPlot().setRangeAxis(new LogAxis(label));
			rangeAxisIsLog = true;
		//}
		for (int i = 0; i < x.length; i++) {
			double y_=y[i];
			if(Double.NEGATIVE_INFINITY!=y_ && Double.POSITIVE_INFINITY!=y_ && !Double.isNaN(y_) && y_>0){
				dataSet.addNewDot(x[i], y[i]);
			}
		}
		dataSet.viewData();
	}

	public void semilogy(DoubleMatrix1D x, DoubleMatrix1D y, String name) {
		newPlot(name);
		if (x == null || y == null || x.size() != x.size()) {
			jMathConsole
					.warn("plot(DoubleMatrix1D x,DoubleMatrix1D y)-- x and y must be of same size");
			return;
		}
		//if (!rangeAxisIsLog) {
			String label = chart.getXYPlot().getRangeAxis().getLabel();
			chart.getXYPlot().setRangeAxis(new LogAxis(label));
			rangeAxisIsLog = true;
		//}
		for (int i = 0; i < x.size(); i++) {
			double y_=y.getQuick(i);
			if(Double.NEGATIVE_INFINITY!=y_ && Double.POSITIVE_INFINITY!=y_ && !Double.isNaN(y_) && y_>0){
				dataSet.addNewDot(x.get(i), y_);
			}
		}
		dataSet.viewData();
	}

	public void setJMathConsole(JMathConsole mathConsole) {
		jMathConsole = mathConsole;
	}
}
